/*
*   本文件封装了应用层需直接调用的核心接口，屏蔽了底层硬件和 FreeRTOS 内核的复杂操作，
*   应用层只需调用这些接口即可完成 Modbus 主机的事件管理、请求等待、错误处理。
*/

/* ----------------------- Modbus includes ----------------------------------*/
#include "mb.h"           // Modbus 核心头文件（通用错误码、模式定义）
#include "mb_m.h"         // Modbus 主机核心头文件（主机事件类型、请求错误码）
#include "mbport.h"       // Modbus 端口抽象层头文件（声明端口接口）
#include "port.h"         // 平台端口适配头文件（硬件/POS 相关定义）

#include "FreeRTOS.h"     // FreeRTOS 核心头文件（内核功能）
#include "task.h"         // FreeRTOS 任务头文件（任务调度）
#include "queue.h"        // FreeRTOS 队列头文件（队列操作，本文件未直接使用）
#include "event_groups.h" // FreeRTOS 事件组头文件（事件同步核心）
#include "semphr.h"       // FreeRTOS 信号量



// 条件编译：仅当启用 RTU 或 ASCII 主机模式时，编译以下接口代码
#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0


#ifndef portVECTACTIVE_MASK
// 定义 VECTACTIVE 字段掩码（低9位，覆盖所有可能的中断号）
#define portVECTACTIVE_MASK  (0xFFUL)
#endif

/* ----------------------- Defines ------------------------------------------*/

// 1. 轮询事件掩码：供 xMBMasterPortEventGet() 使用，定义协议栈主循环需关注的核心事件
// 事件含义：
// - EV_MASTER_READY：主机就绪（可发起新请求）
// - EV_MASTER_FRAME_RECEIVED：从机响应帧接收完成
// - EV_MASTER_EXECUTE：需执行功能码处理（解析响应帧）
// - EV_MASTER_FRAME_SENT：主机请求帧发送完成
// - EV_MASTER_ERROR_PROCESS：需处理错误（超时、接收错误等）
#define MB_EVENT_POLL_MASK      (EventBits_t)(EV_MASTER_READY |          \
											EV_MASTER_FRAME_RECEIVED | \
											EV_MASTER_EXECUTE |        \
											EV_MASTER_FRAME_SENT |     \
											EV_MASTER_ERROR_PROCESS)


// 2. 请求等待事件掩码：供 eMBMasterWaitRequestFinish() 使用，定义应用层需关注的请求结果事件
// 事件含义：
// - EV_MASTER_PROCESS_SUCESS：请求处理成功
// - EV_MASTER_ERROR_RESPOND_TIMEOUT：从机响应超时
// - EV_MASTER_ERROR_RECEIVE_DATA：接收数据错误（帧格式/校验错）
// - EV_MASTER_ERROR_EXECUTE_FUNCTION：功能码执行错误（从机返回异常码）

#define MB_EVENT_REQ_MASK 					(EventBits_t)(EV_MASTER_PROCESS_SUCESS | \
														 EV_MASTER_ERROR_RESPOND_TIMEOUT | \
														 EV_MASTER_ERROR_RECEIVE_DATA |    \
														 EV_MASTER_ERROR_EXECUTE_FUNCTION)


/* ----------------------- Variables ----------------------------------------*/
static SemaphoreHandle_t xSemaphorMasterHdl;   // 主机二值信号量句柄：保护主机资源，防止多任务并发冲突
static EventGroupHandle_t xEventGroupMasterHdl;// 主机事件组句柄：管理所有主机事件（发送、接收、错误等）

/* ----------------------- Start implementation -----------------------------*/

/**
 * @brief  Modbus 主机事件组初始化接口
 * @note   为主机创建 FreeRTOS 事件组，用于后续事件的发送（Post）和接收（Get），
 *         通常在主机初始化（eMBMasterInit）时被调用。
 * @param  无
 * @return BOOL - 初始化结果（TRUE=成功，本实现默认成功；实际可根据 xEventGroupCreate 返回值判断）
 */
BOOL xMBMasterPortEventInit(void)
{
    // 创建 FreeRTOS 事件组：xEventGroupCreate() 返回事件组句柄，失败时返回 NULL
    xEventGroupMasterHdl = xEventGroupCreate();
		if(xEventGroupMasterHdl==NULL) return FALSE;
    return TRUE;
}

/**
 * @brief  Modbus 主机事件发送接口
 * @note   向事件组发送指定事件（如“响应超时”“接收完成”），触发对应的处理逻辑（如主循环处理、应用层等待），
 *         自动判断执行上下文（ISR/任务），选择安全的事件设置接口。
 * @param  eEvent - 待发送的主机事件（eMBMasterEventType 枚举类型，如 EV_MASTER_FRAME_RECEIVED）
 * @return BOOL - 事件发送结果（TRUE=成功，FALSE=失败）
 */
BOOL xMBMasterPortEventPost(eMBMasterEventType eEvent)
{
    BOOL bStatus = FALSE;       // 事件发送结果：默认失败
    eMBMasterEventType eTempEvent = eEvent; // 临时存储事件

    // 检查中断控制状态寄存器 判断是否在中断中
		//读取 ARM Cortex-M 内核的硬件寄存器状态 来判断当前是否处于中断上下文
	  //portNVIC_INT_CTRL_REG 是 ARM Cortex-M 内核中 NVIC（嵌套向量中断控制器)
	  //portVECTACTIVE_MASK（提取有效字段）portVECTACTIVE_MASK 的值固定为 0xFFUL（二进制 11111111），其作用是 精确提取 VECTACTIVE 字段
    if ((portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK) != 0) {
        // 高优先级任务唤醒标志：默认未唤醒
        BaseType_t xHigherPriorityTaskWoken = pdFALSE;

        // 调用 ISR 安全版事件设置接口：xEventGroupSetBitsFromISR()
        // 参数：事件组句柄 → 待设置事件 → 高优先级任务唤醒标志（输出）
        BaseType_t xResult = xEventGroupSetBitsFromISR(xEventGroupMasterHdl,
            (EventBits_t)eTempEvent,
            &xHigherPriorityTaskWoken);

        // 检查事件设置结果
        if (xResult == pdPASS) {
            // 事件设置成功：若唤醒了高优先级任务，触发上下文切换
            portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
            bStatus = TRUE; // 标记发送成功
        } else {
            bStatus = FALSE; // 标记发送失败（如事件组资源不足）
        }
    } else {
        /* 分支2：任务上下文（使用普通事件设置接口） */
        // 调用普通版事件设置接口：xEventGroupSetBits()
        // 忽略返回值：注释说明“即使事件位被自动清除（如等待任务已唤醒），也不影响逻辑”
        (void)xEventGroupSetBits(xEventGroupMasterHdl, (EventBits_t)eTempEvent);
        bStatus = TRUE; // 任务上下文设置成功率极高，直接标记成功
    }
    return bStatus;
}

/**
 * @brief  Modbus 主机事件接收接口
 * @note   从事件组中接收“轮询相关事件”（MB_EVENT_POLL_MASK 定义的事件），供协议栈主循环（eMBMasterPoll）调用，获取需处理的事件并驱动状态机。
 * @param  eEvent - 输出参数：存储接收到的事件
 * @return BOOL - 事件接收结果（TRUE=接收到有效事件，FALSE=未接收到）
 */
BOOL xMBMasterPortEventGet(eMBMasterEventType* eEvent)
{
    EventBits_t uxBits; // 存储从事件组中获取的事件位
    BOOL xEventHappened = FALSE; // 事件接收结果：默认未接收到

    // 等待事件组中的“轮询事件”
    uxBits = xEventGroupWaitBits(xEventGroupMasterHdl, //事件组句柄
        MB_EVENT_POLL_MASK,   // 等待的事件掩码（仅关注轮询相关事件）
        pdTRUE,         // 获取事件后自动清除对应的事件位（避免重复处理）      
        pdFALSE,        // 无需等待所有事件位，只要有一个事件位被设置就返回
        portMAX_DELAY); // 永久等待（直到有事件触发)  

    // 检查是否接收到有效轮询事件
    if (uxBits & MB_EVENT_POLL_MASK) {
        *eEvent = (eMBMasterEventType)(uxBits & MB_EVENT_POLL_MASK); // 存储有效事件
        xEventHappened = TRUE; // 标记接收到事件
    } else {
        *eEvent = (eMBMasterEventType)uxBits; // 存储无效事件（用于调试）
        xEventHappened = FALSE; // 标记未接收到事件
    }
    return xEventHappened;
}

/**
 * @brief  Modbus 主机 OS 资源初始化接口
 * @note   初始化 FreeRTOS 资源（此处为互斥信号量），用于保护主机资源的并发访问，
 *         通常在主机初始化（eMBMasterInit）时被调用；若不使用 OS，此函数可空实现。
 * @param  无
 * @return 无
 */
void vMBMasterOsResInit(void)
{
    // 创建二进制信号量：用于主机资源的互斥访问（初始值为 1，可用状态）
    xSemaphorMasterHdl = xSemaphoreCreateBinary();
}

/**
 * @brief  Modbus 主机运行资源获取接口
 * @note   应用层发起 Modbus 请求前，需先获取此资源（信号量），确保同一时间仅一个请求执行，
 *         避免多任务并发导致的协议混乱；若不使用 OS，此函数可直接返回 TRUE。
 * @param  lTimeOut - 等待超时时间（单位：FreeRTOS 系统节拍，lTimeOut=-1 表示永久等待）
 * @return BOOL - 资源获取结果（本实现默认成功；实际可根据 xSemaphoreTake 返回值判断）
 */
BOOL xMBMasterRunResTake(LONG lTimeOut)
{
    // 获取信号量：等待指定时间，超时则返回失败
    BaseType_t res = xSemaphoreTake(xSemaphorMasterHdl, lTimeOut);
    if (res == pdTRUE) return TRUE;
    return FALSE;
}

/**
 * @brief  Modbus 主机运行资源释放接口
 * @note   应用层请求处理完成后，需释放此资源（信号量），允许其他任务获取资源发起新请求；
 *         若不使用 OS，此函数可空实现。
 * @param  无
 * @return 无
 */
void vMBMasterRunResRelease(void)
{
    // 释放信号量
    xSemaphoreGive(xSemaphorMasterHdl);
}

/**
 * @brief  Modbus 主机“响应超时”错误回调函数
 * @note   当从机未在规定时间内响应主机请求时，协议栈会调用此函数，
 *         功能是向事件组发送“响应超时事件”，通知应用层处理超时逻辑（如重试、日志）。
 * @param  ucDestAddress - 目标从机地址（超时请求的从机地址）
 * @param  pucPDUData    - PDU 数据缓冲区（超时请求的 PDU 内容，用于调试）
 * @param  ucPDULength   - PDU 数据长度（超时请求的 PDU 长度，用于调试）
 * @return 无
 */
void vMBMasterErrorCBRespondTimeout(UCHAR ucDestAddress, const UCHAR* pucPDUData,
    USHORT ucPDULength)
{
    // 向事件组发送“响应超时事件”
    xMBMasterPortEventPost(EV_MASTER_ERROR_RESPOND_TIMEOUT);
    // 扩展点：应用层可在此添加自定义逻辑（如打印超时日志、记录超时次数）
}

/**
 * @brief  Modbus 主机“接收数据错误”回调函数
 * @note   当主机接收到的从机响应帧格式错误、校验失败时，协议栈会调用此函数，
 *         向事件组发送“接收数据错误事件”，通知应用层处理接收错误。
 * @param  ucDestAddress - 目标从机地址（错误响应的从机地址）
 * @param  pucPDUData    - PDU 数据缓冲区（错误响应的 PDU 内容，用于调试）
 * @param  ucPDULength   - PDU 数据长度（错误响应的 PDU 长度，用于调试）
 * @return 无
 */
void vMBMasterErrorCBReceiveData(UCHAR ucDestAddress, const UCHAR* pucPDUData,
    USHORT ucPDULength)
{
    // 向事件组发送“接收数据错误事件”
    xMBMasterPortEventPost(EV_MASTER_ERROR_RECEIVE_DATA);
    // 扩展点：应用层可在此添加自定义逻辑（如打印接收错误日志、重新接收）
}

/**
 * @brief  Modbus 主机“功能码执行错误”回调函数
 * @note   当从机返回“功能码异常响应”（如非法寄存器地址、非法数据值）时，协议栈会调用此函数，
 *         向事件组发送“功能码执行错误事件”，通知应用层处理执行错误。
 * @param  ucDestAddress - 目标从机地址（异常响应的从机地址）
 * @param  pucPDUData    - PDU 数据缓冲区（异常响应的 PDU 内容，含异常码）
 * @param  ucPDULength   - PDU 数据长度（异常响应的 PDU 长度，用于调试）
 * @return 无
 */
void vMBMasterErrorCBExecuteFunction(UCHAR ucDestAddress, const UCHAR* pucPDUData,
    USHORT ucPDULength)
{
    // 向事件组发送“功能码执行错误事件”
    xMBMasterPortEventPost(EV_MASTER_ERROR_EXECUTE_FUNCTION);
    // 扩展点：应用层可在此添加自定义逻辑（如解析异常码、调整请求参数）
}

/**
 * @brief  Modbus 主机“请求处理成功”回调函数
 * @note   当从机响应正常、功能码执行完成时，协议栈会调用此函数， 向事件组发送“请求处理成功事件”，通知应用层获取处理结果。
 * @param  无
 * @return 无
 */
void vMBMasterCBRequestScuuess(void)
{
    // 向事件组发送“请求处理成功事件”
    xMBMasterPortEventPost(EV_MASTER_PROCESS_SUCESS);
    // 扩展点：应用层可在此添加自定义逻辑（如打印成功日志、更新数据标志）
}


/**
 * @brief  Modbus 主机等待请求处理完成接口
 * @note   1. 应用层发起请求（如 eMBMasterReqReadHoldingRegister）后，需立即调用此函数，
 *            函数会阻塞当前任务，直到请求处理完成（成功或错误）或超时；
 *         2. 等待的结果通过 FreeRTOS 事件组实现（监听 MB_EVENT_REQ_MASK 定义的结果事件），
 *            事件由协议栈底层（如错误回调、成功回调）发送；
 *         3. 超时时间固定为 1000ms（可根据实际需求修改，如改为 portMAX_DELAY 永久等待），
 *            超时后返回默认错误（需结合业务判断是否重试）。
 * @param  无
 * @return eMBMasterReqErrCode - 请求处理结果（枚举类型，应用层可通过此码判断请求状态）：
 *                               - MB_MRE_NO_ERR：请求处理成功（从机正常响应，数据有效）；
 *                               - MB_MRE_TIMEDOUT：请求超时（等待结果超过 1000ms，未收到任何结果事件）；
 *                               - MB_MRE_REV_DATA：接收数据错误（从机响应帧格式非法、校验失败等）；
 *                               - MB_MRE_EXE_FUN：功能码执行错误（从机返回异常码，如非法寄存器地址、非法数据值）。
 */
eMBMasterReqErrCode eMBMasterWaitRequestFinish(void)
{
    // 1. 初始化请求错误码：默认设为“成功”（MB_MRE_NO_ERR），后续根据事件修改
    eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR;
    // 2. 存储从事件组接收到的结果事件（类型与 eMBMasterEventType 枚举对应）
    eMBMasterEventType xRecvedEvent;

    // 3. 核心操作：等待事件组中的“请求结果事件”（MB_EVENT_REQ_MASK 定义的事件）
    EventBits_t uxBits = xEventGroupWaitBits(xEventGroupMasterHdl,
        MB_EVENT_REQ_MASK,//等待的事件掩码（仅关注“成功/超时/接收错误/执行错误”4类结果事件）
        pdTRUE,  //接收到事件后，自动清除对应的事件位
        pdFALSE, //无需等待所有事件位，只要有一个事件位被设置就立即返回   
        1000);   //等待超时时间          

    // 4. 将接收到的事件位转换为 Modbus 主机事件类型（eMBMasterEventType）
    xRecvedEvent = (eMBMasterEventType)(uxBits);

    // 5. 判断是否接收到有效事件（uxBits != 0 表示未超时，且收到至少一个事件）
    if (xRecvedEvent) {
        // 5.1 （可选校验）判断接收到的事件是否在“请求结果事件掩码”内（防止接收无关事件）
        if (!(xRecvedEvent & MB_EVENT_REQ_MASK)) {
            // 若事件不在掩码内（异常情况，如接收了轮询事件），此处可添加错误处理（如日志打印）
            // 本实现暂不处理，可根据项目需求扩展
        }
        // 5.2 根据接收到的事件，设置对应的错误码
        else if (xRecvedEvent & EV_MASTER_PROCESS_SUCESS) {
            // 事件：请求处理成功 → 错误码设为“无错误”
            eErrStatus = MB_MRE_NO_ERR;
        } else if (xRecvedEvent & EV_MASTER_ERROR_RESPOND_TIMEOUT) {
            // 事件：从机响应超时 → 错误码设为“超时”
            eErrStatus = MB_MRE_TIMEDOUT;
        } else if (xRecvedEvent & EV_MASTER_ERROR_RECEIVE_DATA) {
            // 事件：接收数据错误 → 错误码设为“接收错误”
            eErrStatus = MB_MRE_REV_DATA;
        } else if (xRecvedEvent & EV_MASTER_ERROR_EXECUTE_FUNCTION) {
            // 事件：功能码执行错误 → 错误码设为“执行错误”
            eErrStatus = MB_MRE_EXE_FUN;
        }
    } else {
        eErrStatus = MB_MRE_TIMEDOUT;
    }

    return eErrStatus;
}

#endif
